package com.ruoyi.business.youdaoController.shangyou;

import com.ruoyi.business.services.HttpService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.SaveType;
import com.ruoyi.common.utils.EncrypDES;
import com.ruoyi.common.utils.GetUrlParam;
import com.ruoyi.common.utils.OtherUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.vo.R;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

/**
 * 其他渠道->Newmob
 */
@RestController
@RequestMapping("ownOtherToNewmobApi")
public class OtherToNewmobController {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private HttpService httpService;

    private final static String CLASSESEN = "youdao";


    /**
     * 接收下游请求并转发给第三方 Newmob
     * 请求示例：/ownOtherToNewmobApi/send?channelId=xxx&dmpid=xxx&其他参数...
     * 
     * @param request
     * @return
     * @throws Exception
     */
    @Log(title = "有道", businessType = BusinessType.ESCALATION, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/send")
    public Object send(HttpServletRequest request) throws Exception {
        String queryString = request.getQueryString();
        String channelId = request.getParameter("channelId");
        String dmpid = request.getParameter("dmpid");
        
        // 验证必需参数
        if(StringUtils.isBlank(channelId) || "null".equals(channelId)){
            return R.failure().msg("channelId不能为空");
        }
        if(StringUtils.isBlank(dmpid) || "null".equals(dmpid)){
            return R.failure().msg("dmpid不能为空");
        }

        // 解析请求参数
        Map<String, Object> baseParamsMap = GetUrlParam.queryStrToMap(queryString);
        
        // 移除内部使用的参数
        baseParamsMap.remove("channelId");
        baseParamsMap.remove("dmpid");

        // 从Redis缓存获取渠道配置
        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        if(channelDetail == null){
            return R.failure().msg("channelId不正确");
        }
        
        // 从渠道配置的request_address中解析tid参数
        String url = channelDetail.get("request_address") + "";
        String requestAddress = GetUrlParam.getRequestAddress(url);
        String staticParameters = GetUrlParam.TruncateUrlPage(url);
        Map<String, Object> staticParamsMap = GetUrlParam.queryStrToMap(staticParameters);
        String tid = getMapValue(staticParamsMap, "tid");
        if(StringUtils.isBlank(tid) || "null".equals(tid)){
            return R.failure().msg("渠道request_address中tid参数未配置");
        }

        // 处理用户代理参数
        String ua = getMapValue(baseParamsMap, "user_agent");
        if(StringUtils.isNotBlank(ua) && !"null".equals(ua)){
            // ua = URLDecoder.decode(ua, Constants.UTF8);
        }

        String originalCallback = getMapValue(baseParamsMap, "callback_url");
        if(StringUtils.isBlank(originalCallback) || "null".equals(originalCallback)){
            return R.failure().msg("callback_url不能为空");
        }

        // 构建回调URL
        String callbackUrl = buildCallbackUrl(request, channelId, dmpid, originalCallback);

        // 构建发送给第三方的参数映射
        Map<String, Object> newmobParamsMap = new HashMap<>();
        
        // 必需参数
        newmobParamsMap.put("tid", tid);
        newmobParamsMap.put("request_id", dmpid); // 使用dmpid作为request_id
        newmobParamsMap.put("callback_url", URLEncoder.encode(callbackUrl, Constants.UTF8));
        
        // 直接循环 baseParamsMap，将所有参数加入 newmobParamsMap（已存在的key不覆盖）
        for (Map.Entry<String, Object> entry : baseParamsMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue() == null ? "" : entry.getValue().toString();
            // 跳过已存在的必填参数，避免覆盖
            if (newmobParamsMap.containsKey(key)) {
                continue;
            }
            if (StringUtils.isNotBlank(value) && !"null".equals(value) && !value.startsWith("__") && !value.endsWith("__")) {
                newmobParamsMap.put(key, value);
            }
        }
        

        // 构建请求参数字符串
        List<String> tempList = new ArrayList<>();
        for(String key: newmobParamsMap.keySet()){
            String val = newmobParamsMap.get(key) + "";
            if(!"null".equals(val) && StringUtils.isNotBlank(val)){
                tempList.add(key+"="+val);
            }
        }
        String requestParameters = String.join("&", tempList);

        // 发送请求到第三方
        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "click";
        httpService.sendGet(requestAddress, requestParameters, null, ua, uuid, reqType);
        
        return R.success().msg(uuid);
    }

    /**
     * 处理第三方回调
     * 
     * @param request
     * @param channelId
     * @param dmpid
     * @param encryptedUrl
     * @return
     * @throws Exception
     */
    @Log(title = "有道", businessType = BusinessType.CALLBACK, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/callback/{channelId}/{dmpid}/{encryptedUrl}")
    public Object callback(HttpServletRequest request, 
                          @PathVariable("channelId") String channelId, 
                          @PathVariable("dmpid") String dmpid,
                          @PathVariable("encryptedUrl") String encryptedUrl) throws Exception {
        
        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        if(channelDetail == null){
            return R.failure().msg("channelId不正确");
        }

        String queryString = request.getQueryString();
        EncrypDES encrypDES = new EncrypDES();
        String requestAddress = encrypDES.decrypt(encryptedUrl);
        // 移除 action 和 action_time 参数
        if (StringUtils.isNotBlank(queryString)) {
            String[] params = queryString.split("&");
            List<String> filteredParams = new ArrayList<>();
            for (String param : params) {
                if (param.startsWith("action=") || param.startsWith("action_time=")) {
                    continue;
                }
                filteredParams.add(param);
            }
            queryString = String.join("&", filteredParams);
        }

        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "callback";
        httpService.sendGet(requestAddress, queryString, null, null, uuid, reqType);
        
        return R.success();
    }

    /**
     * 构建回调URL
     */
    private String buildCallbackUrl(HttpServletRequest request, String channelId, String dmpid, String originalCallback) throws Exception {
        EncrypDES encrypDES = new EncrypDES();
        originalCallback = URLDecoder.decode(originalCallback, Constants.UTF8);
        String callbackAddress = GetUrlParam.getRequestAddress(originalCallback);
        String callbackParams = GetUrlParam.TruncateUrlPage(originalCallback);
        
        // 构建我们的中转回调URL
        String callbackBase = OtherUtils.getServerUrl(request) + "ownOtherToNewmobApi/callback/"+channelId+"/"+dmpid+"/";
        String encrypt_u = encrypDES.encrypt(callbackAddress);
        String callbackUrl = callbackBase + encrypt_u;
        
        if(StringUtils.isNotBlank(callbackParams)){
            callbackUrl += "?" + callbackParams + "&action=__ACTION__&action_time=__ACTION_TIME__";
        } else {
            callbackUrl += "?action=__ACTION__&action_time=__ACTION_TIME__";
        }
        
        return callbackUrl;
    }



    /**
     * 安全获取Map中的值
     */
    private String getMapValue(Map<String, Object> map, String key){
        if(map == null){
            return "";
        }
        if(map.get(key) == null){
            return "";
        }
        return map.get(key)+"";
    }
}